home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
smaltalk
/
manchest.lha
/
MANCHESTER
/
manchester
/
2.3
/
removing-active-subviews.st
< prev
next >
Wrap
Text File
|
1993-07-24
|
5KB
|
154 lines
" NAME removing-active-subviews
AUTHOR neild@cs.man.ac.uk
CONTRIBUTOR neild@cs.man.ac.uk
FUNCTION allows views whose controllers are active to be removed
ST-VERSIONS 2.2 2.3
PREREQUISITES
CONFLICTS
DISTRIBUTION global
VERSION 1.1
DATE 15 Mar 1990
SUMMARY removing-active-subviews
In the search for an ever better user interface I built a view structure
where one of the views had a sub view removed, and a new one added, as a
result of a menu command initiated from the removed view (before it was
removed :-) ). It all fell apart because the method in the model that
causes the changing of the views returns to the controller of, a now
released, view whose super view is also not what it was. The following
changes alleviate this problem by providing a mechanism that allows control
to jump up the stack to a 'higher' controller with a view whose super view
hasn't changed, and thus hasn't been removed or released.
To use this mechanism, either pass the controller to the model and then
send it Controller|exitControlLoop once any actions that cause views to be
removed are complete, or rely on the test in
Controller|controlInitialise. Reimplement Controller|controlToNextLevel if
you don't want control to exit to the ControlManager, i.e. for the
controller of the view whose sub views are changed dynamically.
This takes a while to file in as all subclasses of Controller are recompiled.
This mechanism may be replaced for 2.5 by one based on exceptions.
"!
Object subclass: #Controller
instanceVariableNames: 'model view sensor exitBlock '
classVariableNames: ''
poolDictionaries: ''
category: 'Interface-Framework'!
| ebi |
Controller withAllSubclasses do: [ :cc |
ebi _ cc allInstVarNames indexOf: 'exitBlock'.
cc allInstancesDo: [ :ci |
ci instVarAt: ebi put: [] ] ]!
!Controller methodsFor: 'basic control sequence'!
startUpWithExternalExitBy: anExitBlock
"Give control to the receiver. The default control sequence is to initialize
(see Controller|controlInitialize), to loop (see Controller|controlLoop),
and
then to terminate (see Controller|controlTerminate). After this sequence,
control is returned to the sender of Control|startUp:. The receiver's
control
sequence is used to coordinate the interaction of its view and model.
In general,
this consists of polling the sensor for user input, testing the input
with respect
to the current display of the view, and updating the model to reflect
intended
changes. anExitBlock allows for an abnormal exit from the control loop
(see
Controller|startUp and Controller|exitControlLoop). This is necessary
if an
action from this controller, or that of a sub view, causes the view
to change
its top view or be released."
exitBlock _ anExitBlock.
self controlInitialize.
self controlLoop.
self controlTerminate!
exitControlLoop
"Cause control to be returned immediately to some higher controller
as defined
by the exitBlock (see Controller|controlToNextLevel and Controller|startUp).
This method is not expected to return to its sender. It allows the
suspended
method contexts of Controllers whose views have been removed to be
lost.
This is necessary if the controller of some sub view in a view hierarchy
initiates an action that causes one of its super views to be removed
from
the hierarchy, e.g. as a result of a menu action in the controller's
model."
exitBlock isNil ifTrue: [ self error: 'exit block not defined' ].
exitBlock value! !
!NoController methodsFor: 'basic control sequence'!
startUpWithExternalExitBy: anExitBlock
"I do nothing."
^self! !
!Controller methodsFor: 'basic control sequence'!
startUp
"Give control to the receiver. The default control sequence is to initialize
(see Controller|controlInitialize), to loop (see Controller|controlLoop),
and
then to terminate (see Controller|controlTerminate). After this sequence,
control is returned to the sender of Control|startUp. The receiver's
control
sequence is used to coordinate the interaction of its view and model.
In general,
this consists of polling the sensor for user input, testing the input
with respect
to the current display of the view, and updating the model to reflect
intended
changes."
self startUpWithExternalExitBy: [ ^self ]! !
!Controller methodsFor: 'control defaults'!
controlToNextLevel
"Pass control to the next control level, that is, to the Controller
of a subView of
the receiver's view if possible. The receiver finds the subView (if
any) whose controller
wants control and sends that controller the message startUpWithExternalExitBy:.
If
that controller is required to exit from its control loop by Controller|exitControlLoop
then this also exits its control loop."
| aView |
aView _ view subViewWantingControl.
aView ~~ nil ifTrue: [ aView controller
startUpWithExternalExitBy: [ view notNil ifTrue: [ self controlTerminate
]. self exitControlLoop ] ]! !
!Controller methodsFor: 'basic control sequence'!
controlInitialize
"Sent as part of the standard control sequence. It provides
a place in the standard control sequence for initializing the receiver
(taking into account the current state of its model and view). It should
be
redefined in subclasses to perform some specific action."
view isNil ifTrue: [ self exitControlLoop ].
^self! !